{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "demodu_modu_end _to_end.ipynb",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "16J6xfcKWTS4",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "afc45d73-6176-494a-8df2-69b38629b0f0"
      },
      "source": [
        "#!/usr/bin/python\n",
        "# coding = utf-8\n",
        "\n",
        "import numpy as np\n",
        "from keras import metrics, regularizers, backend\n",
        "from keras.utils import np_utils\n",
        "from keras.models import Model\n",
        "from keras.layers import Input, Dense\n",
        "from keras.callbacks import EarlyStopping, ModelCheckpoint\n",
        "import numpy as np\n",
        "import tensorflow as tf\n",
        "import random as rn\n",
        "import os\n",
        "import json\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "from keras import metrics, regularizers, optimizers, backend\n",
        "from keras.callbacks import TensorBoard, EarlyStopping\n",
        "from keras.models import Model\n",
        "from keras.layers import Input, Dense, Dropout, BatchNormalization, Conv2D, Flatten, pooling\n",
        "from keras.utils import np_utils, vis_utils\n",
        "from keras import metrics, regularizers, optimizers, backend\n",
        "from keras.callbacks import TensorBoard, EarlyStopping\n",
        "from keras.models import Model\n",
        "from keras.layers import Input, Dense, LSTM, CuDNNLSTM, Flatten, Dropout, BatchNormalization\n",
        "from keras.utils import np_utils, vis_utils\n",
        "from keras.models import load_model\n",
        "import scipy.io as sio"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Using TensorFlow backend.\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "koLPurz9YH0v",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#端到端调制识别与解调模型定义\n",
        "#xTest 信号数据集\n",
        "   #cumulant 高阶累积量 9个维度\n",
        "   #传入AI模型 调制识别模型 model_modulation\n",
        "   #QPSK解调模型 model_psk4\n",
        "   #8psk解调模型  model_psk8\n",
        "   #16QAM解调模型  model_qam16\n",
        "   #NFeature 9高阶累积量特征个数为9\n",
        "   # return yTest_demodulation 返回的是解调后的数据集\n",
        "   #对输入xTest的每一行序列进行调制识别和按照识别出来的类型送入相应AI解调模型进行解调\n",
        "   #对这一行序列输出每个类型QPSK 1 16QAM 2 8PSK 0的概率，看那个最大\n",
        "def EndToEnd_Demodulation(xTest,cumulant,model_modulation,model_psk4,model_psk8,model_qam16):\n",
        "   yPredict_type = model_modulation.predict(cumulant);\n",
        "   y_Test = np.zeros((xTest.shape[0], xTest.shape[1]));\n",
        "   for i in range(xTest.shape[0]):\n",
        "       P_type=int(np.argmax(yPredict_type[i])); \n",
        "       if P_type == 0 :\n",
        "            #取得xTest的第i行\n",
        "            b=xTest[i]\n",
        "            #对于行向量进行升维度从（，）二维变三维 变为（1，，）\n",
        "            b=b[None,:,:]\n",
        "            #print(b.shape)\n",
        "            #预测得到这一行的码元概率\n",
        "            a=model_psk8.predict(b);\n",
        "            for j in range(a.shape[1]):\n",
        "                y_Test[i][j] = int(np.argmax(a[0][j]))\n",
        "       elif P_type== 1:\n",
        "            #取得xTest的第i行\n",
        "            b=xTest[i]\n",
        "            #对于行向量进行升维度从（，）二维变三维 变为（1，，）\n",
        "            b=b[None,:,:]\n",
        "            #print(b.shape)\n",
        "            #预测得到这一行的码元概率\n",
        "            a=model_psk4.predict(b);\n",
        "            for j in range(a.shape[1]):\n",
        "                y_Test[i][j] = int(np.argmax(a[0][j]))\n",
        "       elif P_type == 2:\n",
        "            #取得xTest的第i行\n",
        "            b=xTest[i]\n",
        "            #对于行向量进行升维度从（，）二维变三维 变为（1，，）\n",
        "            b=b[None,:,:]\n",
        "            #print(b.shape)\n",
        "            #预测得到这一行的码元概率\n",
        "            a=model_qam16.predict(b);\n",
        "            for j in range(a.shape[1]):\n",
        "                y_Test[i][j] = int(np.argmax(a[0][j]))\n",
        "   return y_Test"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CILcVKToxa10",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 134
        },
        "outputId": "0ab893ba-01a5-4901-c912-1936e6d85953"
      },
      "source": [
        "yPredict"
      ],
      "execution_count": 121,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[3., 0., 0., ..., 1., 1., 1.],\n",
              "       [2., 0., 2., ..., 2., 3., 3.],\n",
              "       [1., 0., 0., ..., 3., 1., 3.],\n",
              "       ...,\n",
              "       [0., 1., 2., ..., 0., 2., 1.],\n",
              "       [2., 2., 0., ..., 3., 3., 0.],\n",
              "       [2., 2., 0., ..., 1., 3., 1.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 121
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "j0IvjGSc3Fzh",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 134
        },
        "outputId": "0b109139-60da-4bbe-8c9e-d86c60a4e05a"
      },
      "source": [
        "yTest"
      ],
      "execution_count": 125,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[3, 3, 0, ..., 2, 3, 0],\n",
              "       [2, 0, 1, ..., 2, 2, 0],\n",
              "       [2, 1, 3, ..., 1, 0, 0],\n",
              "       ...,\n",
              "       [0, 1, 2, ..., 0, 2, 1],\n",
              "       [2, 2, 0, ..., 3, 3, 0],\n",
              "       [2, 2, 0, ..., 1, 3, 1]], dtype=uint8)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 125
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "AqMmRfVyXl5Y",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 134
        },
        "outputId": "218135fa-9c9c-4f52-88ad-15ddd3845998"
      },
      "source": [
        "    #载入必要的4PSK信号数据 -10db-20db\n",
        "    #信号序列的列数\n",
        "    N=100\n",
        "    LOW = -10\n",
        "    HIGH = 20\n",
        "    GAP = 2\n",
        "    #信号序列的行数\n",
        "    NTest = 100\n",
        "    #信号序列的列数\n",
        "    L=100\n",
        "    model_modulation = load_model('modulationModel.h5')\n",
        "    model_psk4 = load_model('QPSKDemodulationModel.h5')\n",
        "    model_psk8 = load_model('8PSKDemodulationModel.h5')\n",
        "    model_qam16 = load_model('16QAMDemodulationModel.h5')\n",
        "    #得到计算好的4PSK高阶累积量\n",
        "    cumulant_psk4 = np.loadtxt('./test_cumulant_psk4.csv', delimiter = ',', dtype = float)\n",
        "    test_data_full = sio.loadmat('test_data_demodulation_psk4.mat')\n",
        "    test_data =test_data_full['test_data_demodulation_psk4']\n",
        "\n",
        "    test_data_real = test_data.real\n",
        "    test_data_imag = test_data.imag\n",
        "    #x_data_real = x_data_real.reshape((1000,100))\n",
        "    #x_data_imag = x_data_imag.reshape((1000,100))\n",
        "    test_data_re = np.stack((test_data_real, test_data_imag), axis=2)\n",
        "    xTest = test_data_re[:,0:N]\n",
        "    yTest_full=sio.loadmat('test_label_demodulation_psk4.mat')\n",
        "    yTest= yTest_full['test_label_demodulation_psk4']\n",
        "    yTest.astype(int)"
      ],
      "execution_count": 132,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[3, 3, 0, ..., 2, 3, 0],\n",
              "       [2, 0, 1, ..., 2, 2, 0],\n",
              "       [2, 1, 3, ..., 1, 0, 0],\n",
              "       ...,\n",
              "       [0, 1, 2, ..., 0, 2, 1],\n",
              "       [2, 2, 0, ..., 3, 3, 0],\n",
              "       [2, 2, 0, ..., 1, 3, 1]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 132
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gHHQXFSWuY-5",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#将信号输入端到端的调制识别与解调模型\n",
        "\n",
        "#对输入的4psk信号进行调制识别与解调\n",
        "yPredict=EndToEnd_Demodulation(xTest,cumulant_psk4,model_modulation,model_psk4,model_psk8,model_qam16)\n",
        " "
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "QzV-ZWyi1wTU",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 295
        },
        "outputId": "44f044e0-e9b1-4d78-b1d6-4a6f1f24c594"
      },
      "source": [
        "#解调得到的数据和 原本的标签正例数据进行比较，计算出正确率\n",
        "    predict_curve = np.zeros((2, int((HIGH-LOW)/GAP) + 1)) # snr + Pc\n",
        "\n",
        "     #第一个for循环得到x轴的刻度\n",
        "    for i in range(predict_curve.shape[1]): # snr - [-10 -8 ... 18 20]\n",
        "        predict_curve[0, i] = LOW + GAP * i\n",
        "    #不同信噪比的信号 预测正确的个数\n",
        "    for i in range(test_data_re.shape[0]): \n",
        "        snr_loc = int((test_data_re[i, L,0] - LOW)/GAP);\n",
        "        for j in range(L):\n",
        "          #print(yTest[i,j])\n",
        "          #print(int(np.argmax(yPredict[i,j])))\n",
        "          if yTest[i,j] == int(yPredict[i,j]):\n",
        "            continue\n",
        "          else:\n",
        "            break\n",
        "        #print(j)\n",
        "        if j == L-1 :\n",
        "          predict_curve[1, snr_loc] = predict_curve[1, snr_loc] + 1\n",
        "    #不同信噪比预测正确的百分比，结果应该为噪声越大，预测准确率越低，信噪比越高，预测准确率越高\n",
        "    for i in range(predict_curve.shape[1]): \n",
        "        predict_curve[1, i] = predict_curve[1, i]/(NTest)\n",
        "    \n",
        "    #输入测试集计算预测的准确性，可以看到snr 在10b之下的时候，由于噪声过大，模型解调正确率很低\n",
        "    #当SNR大于等于10db的时候，模型接近百分之百预测正确信号的解调\n",
        "    plt.plot(predict_curve[0], predict_curve[1], 'o-')\n",
        "\n",
        "    plt.grid(True)\n",
        "    #plt.legend(loc='lower right')\n",
        "    plt.xlim((LOW, HIGH))\n",
        "    plt.ylim((0,1))\n",
        "    plt.xlabel('SNR(dB)')\n",
        "    plt.ylabel('Pc')\n",
        "    plt.title('QPSK End to End Modulation-Classification-Demodulation Prediction Accuracy')\n",
        "    plt.savefig('QPSK_End_to_End_Modulation_Classification_Demodulation_accuracy.png', format='png')"
      ],
      "execution_count": 134,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WoFfD9kJ2UpL",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 134
        },
        "outputId": "ab358bdc-e26c-4c45-dd1d-9be8d6d70fbd"
      },
      "source": [
        "#载入8psk信号数据-10db-20db\n",
        "#载入必要的4PSK信号数据 -10db-20db\n",
        "    #信号序列的列数\n",
        "    N=100\n",
        "    LOW = -10\n",
        "    HIGH = 20\n",
        "    GAP = 2\n",
        "    #信号序列的行数\n",
        "    NTest = 100\n",
        "    #信号序列的列数\n",
        "    L=100\n",
        "    model_modulation = load_model('modulationModel.h5')\n",
        "    model_psk4 = load_model('QPSKDemodulationModel.h5')\n",
        "    model_psk8 = load_model('8PSKDemodulationModel.h5')\n",
        "    model_qam16 = load_model('16QAMDemodulationModel.h5')\n",
        "    #得到计算好的8PSK高阶累积量\n",
        "    cumulant_psk8 = np.loadtxt('./test_cumulant_psk8.csv', delimiter = ',', dtype = float)\n",
        "    test_data_full = sio.loadmat('test_data_demodulation_psk8.mat')\n",
        "    test_data =test_data_full['test_data_demodulation_psk8']\n",
        "\n",
        "    test_data_real = test_data.real\n",
        "    test_data_imag = test_data.imag\n",
        "    #x_data_real = x_data_real.reshape((1000,100))\n",
        "    #x_data_imag = x_data_imag.reshape((1000,100))\n",
        "    test_data_re = np.stack((test_data_real, test_data_imag), axis=2)\n",
        "    xTest = test_data_re[:,0:N]\n",
        "    yTest_full=sio.loadmat('test_label_demodulation_psk8.mat')\n",
        "    yTest= yTest_full['test_label_demodulation_psk8']\n",
        "    yTest.astype(int)"
      ],
      "execution_count": 135,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[0, 5, 3, ..., 7, 6, 3],\n",
              "       [2, 2, 3, ..., 7, 2, 6],\n",
              "       [5, 0, 6, ..., 2, 2, 3],\n",
              "       ...,\n",
              "       [4, 2, 6, ..., 6, 5, 1],\n",
              "       [7, 0, 5, ..., 0, 0, 4],\n",
              "       [7, 6, 7, ..., 6, 2, 0]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 135
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zAPUMuO5B2Qo",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#将8psk信号输入端到端的调制识别与解调模型\n",
        "#对输入的8psk信号进行调制识别与解调\n",
        "yPredict=EndToEnd_Demodulation(xTest,cumulant_psk8,model_modulation,model_psk4,model_psk8,model_qam16)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rTYzU9X-B2W9",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 295
        },
        "outputId": "e70e7176-5c4c-48ac-ea31-5c96b39ec4fe"
      },
      "source": [
        "#解调得到的8psk数据和 原本的标签正例数据进行比较，计算出正确率\n",
        "    predict_curve = np.zeros((2, int((HIGH-LOW)/GAP) + 1)) # snr + Pc\n",
        "    for i in range(predict_curve.shape[1]): # snr - [-10 -8 ... 18 20]\n",
        "        predict_curve[0, i] = LOW + GAP * i\n",
        "    #不同信噪比的信号 预测正确的个数\n",
        "    for i in range(test_data_re.shape[0]):\n",
        "        snr_loc = int((test_data_re[i, L,0] - LOW)/GAP);\n",
        "        for j in range(L):\n",
        "          #print(yTest[i,j])\n",
        "          #print(int(np.argmax(yPredict[i,j])))\n",
        "          if yTest[i,j] == int(yPredict[i,j]):\n",
        "            continue\n",
        "          else:\n",
        "            break\n",
        "        #print(j)\n",
        "        if j == L-1 :\n",
        "          predict_curve[1, snr_loc] = predict_curve[1, snr_loc] + 1\n",
        "    #不同信噪比预测正确的百分比，结果应该为噪声越大，预测准确率越低，信噪比越高，预测准确率越高\n",
        "    for i in range(predict_curve.shape[1]): \n",
        "        predict_curve[1, i] = predict_curve[1, i]/(NTest)\n",
        "    \n",
        "    #输入测试集计算预测的准确性，可以看到snr 在10b之下的时候，由于噪声过大，模型解调正确率很低\n",
        "    #当SNR大于等于10db的时候，模型接近百分之百预测正确信号的解调\n",
        "    plt.plot(predict_curve[0], predict_curve[1], 'o-')\n",
        "\n",
        "    plt.grid(True)\n",
        "    #plt.legend(loc='lower right')\n",
        "    plt.xlim((LOW, HIGH))\n",
        "    plt.ylim((0,1))\n",
        "    plt.xlabel('SNR(dB)')\n",
        "    plt.ylabel('Pc')\n",
        "    plt.title('8PSK End to End Modulation-Classification-Demodulation Prediction Accuracy')\n",
        "    plt.savefig('8PSK_End_to_End_Modulation_Classification_Demodulation_accuracy.png', format='png')"
      ],
      "execution_count": 139,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "sExTcCbDB2jg",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 134
        },
        "outputId": "2494508e-f5f9-4831-8862-a439c85d8e10"
      },
      "source": [
        "#载入16QAM信号数据20db -44db\n",
        "#载入必要的4PSK信号数据 -10db-20db\n",
        "    #信号序列的列数\n",
        "    N=100\n",
        "    LOW = 20\n",
        "    HIGH = 44\n",
        "    GAP = 2\n",
        "    #信号序列的行数\n",
        "    NTest = 100\n",
        "    #信号序列的列数\n",
        "    L=100\n",
        "    model_modulation = load_model('modulationModel.h5')\n",
        "    model_psk4 = load_model('QPSKDemodulationModel.h5')\n",
        "    model_psk8 = load_model('8PSKDemodulationModel.h5')\n",
        "    model_qam16 = load_model('16QAMDemodulationModel.h5')\n",
        "    #得到计算好的4PSK高阶累积量\n",
        "    cumulant_qam16 = np.loadtxt('./test_cumulant_qam16.csv', delimiter = ',', dtype = float)\n",
        "    test_data_full = sio.loadmat('test_data_demodulation_qam16.mat')\n",
        "    test_data =test_data_full['test_data_demodulation_qam16']\n",
        "\n",
        "    test_data_real = test_data.real\n",
        "    test_data_imag = test_data.imag\n",
        "    #x_data_real = x_data_real.reshape((1000,100))\n",
        "    #x_data_imag = x_data_imag.reshape((1000,100))\n",
        "    test_data_re = np.stack((test_data_real, test_data_imag), axis=2)\n",
        "    xTest = test_data_re[:,0:N]\n",
        "    yTest_full=sio.loadmat('test_label_demodulation_qam16.mat')\n",
        "    yTest= yTest_full['test_label_demodulation_qam16']\n",
        "    yTest.astype(int)"
      ],
      "execution_count": 140,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[ 9, 10, 11, ...,  3, 13,  5],\n",
              "       [11, 14,  7, ..., 10,  4,  5],\n",
              "       [ 3,  0,  9, ...,  3, 15,  3],\n",
              "       ...,\n",
              "       [ 6, 15, 14, ...,  7,  2,  4],\n",
              "       [ 6, 15,  8, ..., 11, 15,  8],\n",
              "       [ 9,  6, 12, ...,  5, 14,  5]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 140
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "60mlmNdDB2p_",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#将16QAM信号输入端到端的调制识别与解调模型\n",
        "#对输入的16qam信号进行调制识别与解调\n",
        "yPredict=EndToEnd_Demodulation(xTest,cumulant_qam16,model_modulation,model_psk4,model_psk8,model_qam16)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IEiupwWWB2vC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 295
        },
        "outputId": "1028d145-faed-46a5-e9cf-5b9ea237d392"
      },
      "source": [
        "#解调得到的16QAM数据和 原本的标签正例数据进行比较，计算出正确率\n",
        "    predict_curve = np.zeros((2, int((HIGH-LOW)/GAP) + 1)) # snr + Pc\n",
        "    for i in range(predict_curve.shape[1]): # snr - [-10 -8 ... 18 20]\n",
        "        predict_curve[0, i] = LOW + GAP * i\n",
        "    #不同信噪比的信号 预测正确的个数\n",
        "    for i in range(test_data_re.shape[0]): \n",
        "        snr_loc = int((test_data_re[i, L,0] - LOW)/GAP);\n",
        "        for j in range(L):\n",
        "          #print(yTest[i,j])\n",
        "          #print(int(np.argmax(yPredict[i,j])))\n",
        "          if yTest[i,j] == int(yPredict[i,j]):\n",
        "            continue\n",
        "          else:\n",
        "            break\n",
        "        #print(j)\n",
        "        if j == L-1 :\n",
        "          predict_curve[1, snr_loc] = predict_curve[1, snr_loc] + 1\n",
        "    #不同信噪比预测正确的百分比，结果应该为噪声越大，预测准确率越低，信噪比越高，预测准确率越高\n",
        "    for i in range(predict_curve.shape[1]): \n",
        "        predict_curve[1, i] = predict_curve[1, i]/(NTest)\n",
        "    \n",
        "    #输入测试集计算预测的准确性，可以看到snr 在10b之下的时候，由于噪声过大，模型解调正确率很低\n",
        "    #当SNR大于等于10db的时候，模型接近百分之百预测正确信号的解调\n",
        "    plt.plot(predict_curve[0], predict_curve[1], 'o-')\n",
        "\n",
        "    plt.grid(True)\n",
        "    #plt.legend(loc='lower right')\n",
        "    plt.xlim((LOW, HIGH))\n",
        "    plt.ylim((0,1))\n",
        "    plt.xlabel('SNR(dB)')\n",
        "    plt.ylabel('Pc')\n",
        "    plt.title('16QAM End to End Modulation-Classification-Demodulation Prediction Accuracy')\n",
        "    plt.savefig('16QAM_End_to_End_Modulation_Classification_Demodulation_accuracy.png', format='png')"
      ],
      "execution_count": 142,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WcDDFK3yq184",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 151
        },
        "outputId": "759ce0e3-f3f8-444b-b751-139b2cb8bf3d"
      },
      "source": [
        "cumulant_psk4 = cumulant_psk4[:,0:9]\n",
        "yPredict_type = model_modulation.predict(cumulant_psk4);\n",
        "print(np.argmax(yPredict_type[1599]))\n",
        "y_Test"
      ],
      "execution_count": 30,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[3., 0., 0., ..., 1., 1., 1.],\n",
              "       [2., 0., 2., ..., 2., 3., 3.],\n",
              "       [1., 0., 0., ..., 3., 1., 3.],\n",
              "       ...,\n",
              "       [0., 1., 2., ..., 0., 2., 1.],\n",
              "       [2., 2., 0., ..., 3., 3., 0.],\n",
              "       [2., 2., 0., ..., 1., 3., 1.]])"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 30
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bcA_dzwL51h5",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "83960a27-7648-4cc4-f3c4-7accfeb6d5f7"
      },
      "source": [
        "y_Test.shape"
      ],
      "execution_count": 58,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(1600, 100)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 58
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kIJjkk84ph35",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "yPredict_type = model_modulation.predict(cumulant_psk4);\n",
        "\n",
        "y_Test = np.zeros((xTest.shape[0], xTest.shape[1]));\n",
        "\n",
        "a=model_psk4.predict(xTest);\n",
        "for i in range(xTest.shape[0]):\n",
        "    for j in range(a.shape[1]):\n",
        "        y_Test[i][j] = np.argmax(a[0][j])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MQvdPaoN7JJ-",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "b=xTest[0]\n",
        "\n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vg-5S_4z74dG",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "8033c0df-5a6f-4499-f004-9b1d5e4d1cf3"
      },
      "source": [
        "b=b[None,:,:]\n",
        "b.shape"
      ],
      "execution_count": 101,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(1, 100, 2)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 101
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fQWNbhHXnEDO",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "y_Test = np.zeros((xTest.shape[0], xTest.shape[1]));"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nAg29koZ9JM_",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "ffdb508e-73f6-4329-b2b0-a0c3894435d7"
      },
      "source": [
        "a=model_psk4.predict(b);\n",
        "\n",
        "print(b.shape)"
      ],
      "execution_count": 102,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "(1, 100, 4)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "reFMMvd4Bl0r",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "i=0\n",
        "for j in range(a.shape[1]):\n",
        "    y_Test[i][j] = np.argmax(a[i][j])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hXPzMec_nfip",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 50
        },
        "outputId": "a9849823-c4de-4d17-b4f4-d9b0a392244a"
      },
      "source": [
        "a[0,3]"
      ],
      "execution_count": 68,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([2.2745896e-04, 1.9879304e-03, 9.9531364e-01, 2.4709080e-03],\n",
              "      dtype=float32)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 68
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JK6f0QRvnhAJ",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}